package com.allen.excelUtils.format;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import net.sf.cglib.reflect.FastClass;
import net.sf.cglib.reflect.FastMethod;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;

import com.allen.excelUtils.column.annotation.CellFormat;
import com.allen.excelUtils.column.annotation.ExcelColumn;
import com.allen.excelUtils.column.annotation.Formatter;
import com.allen.excelUtils.exception.FormatException;
import com.allen.excelUtils.row.DataRow;



/**
 * 行格式化实现类，含单元格格式化注解解析
 * @author allen
 *
 * @param <T>
 */
public class RowFormatterImpl<T> extends RFormatter implements RowFormatter<T> {

	Class<T> cls;
	Field[] fields;
	Map<Class<?>, FormatterObj> formatsMethods = new HashMap<Class<?>, FormatterObj>();
	
	public RowFormatterImpl(Class<T> cls){
		this.cls = cls;
		fields = cls.getDeclaredFields();
		Field.setAccessible(fields, true);
		try {
			init();
		} catch (Exception e) {
			throw new FormatException(e.getMessage(),e);
		}
	}
	
	private void init() throws InstantiationException, IllegalAccessException{
		CellFormat cellFormat = null;
		Formatter formatter = null;
		for (Field field : fields) {
			if (field.isAnnotationPresent(Formatter.class)) {
				formatter = field.getAnnotation(Formatter.class);
				Class<?> _cls = formatter.formatterClass();
				
				if (!formatsMethods.containsKey(_cls)) {
					formatsMethods.put(_cls, new FormatterObj(_cls.newInstance()));
					FormatterObj formatterObj = formatsMethods.get(_cls);
					FastClass fcls = FastClass.create(_cls);
					Method[] methods = _cls.getMethods();
					Method.setAccessible(methods, true);
					for (Method formatMethod : methods) {
						if (formatMethod.isAnnotationPresent(CellFormat.class)) {
							cellFormat = formatMethod.getAnnotation(CellFormat.class);
							formatterObj.put(cellFormat.name(), fcls.getMethod(formatMethod));
						}
					}
				}		
			}	
		}
	}
	
	@Override
	public T format(DataRow row) throws FormatException {
		try {
			T obj= cls.newInstance();
			FastMethod method;
			ExcelColumn excelColumn = null;
			Formatter formatter = null;
			FormatterObj formatterObj = null;
			String _v;
			Object val;

			for (Field field : fields) {
				if (field.isAnnotationPresent(ExcelColumn.class)){
					excelColumn = field.getAnnotation(ExcelColumn.class);
					Cell cell =  row.getCell(field.getName());//根据名称来获取cell值
					
					val = getValue(cell);
					_v = String.valueOf(val);
					if (!excelColumn.nullable() && (null==cell || 
							StringUtils.isBlank(_v))) {
						throw new FormatException(excelColumn.name()+"值不能为空。");
					}
					
					if (StringUtils.isNotBlank(excelColumn.regex())) {
						if(StringUtils.isNotBlank(_v) && !_v.matches(excelColumn.regex())){
							throw new FormatException(excelColumn.name()+"值不符合规则。");
						}
					}
					
					if (field.isAnnotationPresent(Formatter.class)) {
						formatter = field.getAnnotation(Formatter.class);
						//对自定义格式化进行方法调用
						formatterObj = formatsMethods.get(formatter.formatterClass());
						method = formatterObj.getFastMethod(formatter.name());
						val = method.invoke(formatterObj.getObject(), new Object[]{cell});
					}
					field.set(obj, val);
				}
			}
			return obj;
		} catch (Exception e) {
			throw new FormatException(e.getMessage(),e);
		}
	}
	
	private class FormatterObj{
		Map<String, FastMethod> methods = new HashMap<String, FastMethod>();
		public Object object;
		
		public FormatterObj(Object object){
			this.object = object;
		}
		
		public Object getObject(){
			return object;
		}
		
		public void put(String name,FastMethod method) {
			methods.put(name, method);
		}
		
		public FastMethod getFastMethod(String name) {
			return methods.get(name);
		}
	}
}
